/*
 * Copyright (C) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "imageknife_napi.h"
#include "imageknife_internal.h"
#include "imageknife.h"
#include "imageknife_node_animator.h"
#include "imageknife_request.h"
#include "file_cache.h"
#include "option/animator_option_napi.h"
#include "option/imageknife_option_napi.h"

namespace ImageKnifeC {

// static
napi_value ImageKnifeNapi::CreateNativeRoot(napi_env env, napi_callback_info info)
{
    const size_t argSize = 5;
    const size_t contextIndex = 4;
    const size_t syncLoadIndex = 3;
    const size_t optionIndex = 2;
    size_t argc = argSize;
    napi_value args[argSize] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取NodeContent
    ArkUI_NodeContentHandle contentHandle;
    OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);

    // 获取componentId
    size_t length;
    napi_get_value_string_utf8(env, args[1], nullptr, 0, &length);
    char componentId[length + 1];
    napi_get_value_string_utf8(env, args[1], componentId, length + 1, nullptr);

    // 获取ImageKnifeOption
    auto imageKnifeOption = std::make_shared<ImageKnifeOptionNapi>(env, args[optionIndex]);

    // 获取syncLoad
    bool syncLoad = false;
    napi_get_value_bool(env, args[syncLoadIndex], &syncLoad);

    // 设置和覆盖context
    imageKnifeOption->ParseContext(env, args[contextIndex]);
    
    auto imageKnifeNode = ImageKnifeNode::CreateImageKnifeNode(std::string(componentId), imageKnifeOption);
    imageKnifeNode->SyncLoad(syncLoad);
    // 设置contentHandle, 挂载imageNode, 保持Native侧对象到管理类中，维护生命周期。
    ImageKnifeInternal::GetInstance().SetRootNode(componentId, contentHandle, imageKnifeNode);
    
    ImageKnifeInternal::GetInstance().Execute(imageKnifeNode->GetImageKnifeRequest());

    return nullptr;
}

napi_value ImageKnifeNapi::UpdateNativeRoot(napi_env env, napi_callback_info info)
{
    const size_t argSize = 4;
    const size_t contextIndex = 3;
    const size_t syncLoadIndex = 2;
    size_t argc = argSize;
    napi_value args[argSize] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取componentId
    size_t length;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &length);
    char componentId[length + 1];
    napi_get_value_string_utf8(env, args[0], componentId, length + 1, nullptr);

    // 获取imageKnifeOption
    auto imageKnifeOption = std::make_shared<ImageKnifeOptionNapi>(env, args[1]);

    // 获取syncLoad
    bool syncLoad = false;
    napi_get_value_bool(env, args[syncLoadIndex], &syncLoad);
    
    // 设置和覆盖context
    imageKnifeOption->ParseContext(env, args[contextIndex]);
    
    // 找到ImageNode
    auto imageNode =  ImageKnifeInternal::GetInstance().GetImageNode(componentId);
    if (imageNode != nullptr) {
        imageNode->Reuse();
        ImageKnife::GetInstance().CancelRequest(imageNode->GetImageKnifeRequest());
        // 通过imageKnifeOption 更新请求
        imageNode->UpdateImageKnifeRequest(imageKnifeOption);
        // request 更新完成后，更新request的 syncLoad状态
        imageNode->SyncLoad(syncLoad);
        ImageKnifeInternal::GetInstance().Execute(imageNode->GetImageKnifeRequest());
    }

    return nullptr;
}

napi_value ImageKnifeNapi::ClearNativeRoot(napi_env env, napi_callback_info info)
{
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取componentId
    size_t length;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &length);
    char componentId[length+1];
    napi_get_value_string_utf8(env, args[0], componentId, length+1, &length);
    
    // OH_LOG_Print(LOG_APP, LOG_DEBUG, LOG_DOMAIN, "ImageKnifeNapiC", "NAPI ClearNativeRoot componentId=%{public}s", componentId);

    auto imageNode =  ImageKnifeInternal::GetInstance().GetImageNode(componentId);
    if (imageNode != nullptr) {
        imageNode->Clear();
        ImageKnife::GetInstance().CancelRequest(imageNode->GetImageKnifeRequest());
    }
    return nullptr;
}

napi_value ImageKnifeNapi::DestroyNativeRoot(napi_env env, napi_callback_info info)
{
    size_t argc = 1;
    napi_value arg;
    napi_get_cb_info(env, info, &argc, &arg, nullptr, nullptr);

    size_t length;
    napi_get_value_string_utf8(env, arg, nullptr, 0, &length);
    char componentId[length + 1];
    napi_get_value_string_utf8(env, arg, componentId, length + 1, &length);

    std::string id = componentId;

    auto imageNode =  ImageKnifeInternal::GetInstance().GetImageNode(componentId);
    if (imageNode != nullptr) {
        ImageKnife::GetInstance().CancelRequest(imageNode->GetImageKnifeRequest());
        //  从管理类中释放Native侧对象。
        ImageKnifeInternal::GetInstance().DisposeRootNode(id);
    }

    return nullptr;
}

napi_value ImageKnifeNapi::InitFileCache(napi_env env, napi_callback_info info)
{
    // 创建 Promise
    napi_status status;
    const size_t maxArgcSize = 4;
    const size_t maxFileDirLength = 512;
    const size_t maxJsPathLength = 512;
    const size_t mixArgSize = 3;
    const int memorySizeArgIndex = 2;
    const int pathArgIndex = 3;
    napi_value promise = nullptr;

    // 获取传递的参数
    size_t argc = maxArgcSize;
    napi_value args[maxArgcSize];
    status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    if (status != napi_ok) {
        return promise;
    }

    // 获取 filesDir 参数
    size_t strLength = 0;
    char fileDir[maxFileDirLength] = {0};
    status = napi_get_value_string_utf8(env, args[0], fileDir, maxFileDirLength, &strLength);
    if (status != napi_ok || strLength > maxFileDirLength || strLength < 0) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN,
                     "ImageKnifeNapi::InitFileCache",
                     "status is: %{public}d %{public}ld",
                     status, strLength);
        return promise;
    }
    fileDir[strLength] = 0;

    // 获取 size 参数
    int32_t fileSize = 0;
    status = napi_get_value_int32(env, args[1], &fileSize);
    if (status != napi_ok) {
        return promise;
    }

    // 获取 memory 参数
    int32_t memorySize = 0;
    status = napi_get_value_int32(env, args[memorySizeArgIndex], &memorySize);
    if (status != napi_ok) {
        return promise;
    }

    // 获取 path 参数
    std::string path;
    if (argc > mixArgSize) {
        size_t pathLength = 0;
        char jsPath[maxJsPathLength] = {0};
        status = napi_get_value_string_utf8(env, args[pathArgIndex], jsPath, maxJsPathLength, &pathLength);
        if (status != napi_ok) {
            OH_LOG_Print(LOG_APP, LOG_DEBUG, LOG_DOMAIN, "ImageKnifeNapi::InitFileCache",
                         "Failed to get 'path' length");
        }
        if (pathLength > maxJsPathLength || pathLength < 0) {
            OH_LOG_Print(LOG_APP, LOG_DEBUG, LOG_DOMAIN, "ImageKnifeNapi::InitFileCache", "path pathlength error");
            return promise;
        }
        path = std::string(jsPath);
    }

    // 创建异步工作的名称
    napi_value asyncWorkName;
    status = napi_create_string_utf8(env, "InitFileCache", NAPI_AUTO_LENGTH, &asyncWorkName);
    if (status != napi_ok) {
        return promise;
    }

    FileCache::AsyncData *asyncData = new FileCache::AsyncData;
    status = napi_create_promise(env, &asyncData->deferred, &promise);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN,
                     "ImageKnifeNapi::InitFileCache",
                     "Failed to create promise");
        delete asyncData;
        asyncData = nullptr;
        return promise;
    }

    asyncData->fileDir = std::string(fileDir);
    asyncData->size = fileSize;
    asyncData->memory = memorySize;
    asyncData->path = path;
    // 创建异步工作项
    status = napi_create_async_work(env, nullptr, asyncWorkName,
                                    FileCache::StartFileCacheInitThread,
                                    FileCache::FileCacheInitComplete,
                                    asyncData,
                                    &asyncData->asyncWork);
    if (status != napi_ok) {
        delete asyncData;
        asyncData = nullptr;
        return promise;
    }

    // 将异步工作项加入队列
    status = napi_queue_async_work_with_qos(env, asyncData->asyncWork, napi_qos_default);
    if (status != napi_ok) {
        napi_delete_async_work(env, asyncData->asyncWork);
        delete asyncData;
        asyncData = nullptr;
        return promise;
    }

    return promise;
}

napi_value ImageKnifeNapi::Preload(napi_env env, napi_callback_info info)
{
    napi_status status;
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取传入的 request 参数
    napi_value jsRequest = args[0];

    // 从 request 中获取 imageKnifeOption 属性
    napi_value jsImageKnifeOption;
    status = napi_get_named_property(env, jsRequest, "imageKnifeOption", &jsImageKnifeOption);
    if (status != napi_ok) {
        napi_throw_error(env, "ImageKnifeNapi::Preload", "Failed to get 'imageKnifeOption' property from request");
        return nullptr;
    }

    auto imageKnifeOption = std::make_shared<ImageKnifeOptionNapi>(env, jsImageKnifeOption);

    std::shared_ptr<ImageKnifeRequestInternal> request =
        std::dynamic_pointer_cast<ImageKnifeRequestInternal>(ImageKnife::GetInstance().Preload(imageKnifeOption));
    if (!request) {
        napi_throw_error(env, "ImageKnifeNapi::Preload", "Failed to cast request");
        return nullptr;
    }

    request->SetEnv(env);

    // 创建对 jsRequest 的引用并保存到 request 中
    napi_ref jsRequestRef = nullptr;

    // 第四个参数必填项，即使不使用
    status = napi_wrap(env, args[0], request.get(), [](napi_env env, void* data, void* hint) {},
                       nullptr, &jsRequestRef);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN, "ImageKnifeNapi::Preload", "Failed to bind the JavaScript object");
    }

    request->SetJsRequestRef(jsRequestRef);
    return jsRequest;
}

napi_value ImageKnifeNapi::Cancel(napi_env env, napi_callback_info info)
{
    napi_status status;
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    if (status != napi_ok) {
        return nullptr;
    }

    ImageKnifeRequestInternal* request = nullptr;
    status = napi_unwrap(env, args[0], (void**)&request);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN, "ImageKnifeNapi::Cancel", "Failed to unwrap");
        return nullptr;
    }

    if (request == nullptr) {
        OH_LOG_Print(LOG_APP, LOG_DEBUG, LOG_DOMAIN, "ImageKnifeNapi::Cancel", "request is null");
        return nullptr;
    }
    // 恢复成智能指针
    auto requestSharePtr = request->shared_from_this();
    ImageKnife::GetInstance().CancelRequest(requestSharePtr);
    return nullptr;
}

napi_value ImageKnifeNapi::SetMaxRequests(napi_env env, napi_callback_info info)
{
    // 获取 concurrency 参数
    napi_status status;
    // 获取传递的参数数量
    size_t argc = 1;
    napi_value args[1];
    status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    napi_value jsConrrency = args[0];
    int concurrency = 0;
    status = napi_get_value_int32(env, jsConrrency, &concurrency);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN,
                     "ImageKnifeNapi::SetMaxRequests",
                     "Failed to get 'concurrency' parameter");
    }
    ImageKnife::GetInstance().SetMaxRequests(concurrency);
    return nullptr;
}

napi_value ImageKnifeNapi::CreateAnimatorImage(napi_env env, napi_callback_info info)
{
    size_t argc = 5;
    const size_t imageKnifeOptionIndex = 2;
    const size_t animatorOptionIndex = 3;
    const size_t contextIndex = 4;
    napi_value args[5] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    // 获取NodeContent
    ArkUI_NodeContentHandle contentHandle;
    OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &contentHandle);

    // 获取componentId
    size_t length;
    napi_get_value_string_utf8(env, args[1], nullptr, 0, &length);
    char componentId[length + 1];
    napi_get_value_string_utf8(env, args[1], componentId, length + 1, nullptr);

    // 获取ImageKnifeOption
    auto imageKnifeOption = std::make_shared<ImageKnifeOptionNapi>(env, args[imageKnifeOptionIndex]);
    // 设置context
    imageKnifeOption->ParseContext(env, args[contextIndex]);
    // 获取AnimatorOption
    auto animatorOption = std::make_shared<AnimatorOptionNapi>(env, args[animatorOptionIndex]);

    // 创建ImageKnifeNodeAnimator, 并挂载上树
    auto imageKnifeNodeAnimator = ImageKnifeNode::CreateImageKnifeNodeAnimator(componentId,
        imageKnifeOption, animatorOption);
    ImageKnifeInternal::GetInstance().SetRootNode(componentId, contentHandle, imageKnifeNodeAnimator);
    ImageKnifeInternal::GetInstance().Execute(imageKnifeNodeAnimator->GetImageKnifeRequest());
    return nullptr;
}

napi_value ImageKnifeNapi::UpdateAnimatorImage(napi_env env, napi_callback_info info)
{
    size_t argc = 4;
    const size_t animatorOptionIndex = 2;
    const size_t contextIndex = 3;
    napi_value args[5] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取componentId
    size_t length;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &length);
    char componentId[length + 1];
    napi_get_value_string_utf8(env, args[0], componentId, length + 1, nullptr);

    // 获取ImageKnifeOption
    auto imageKnifeOption = std::make_shared<ImageKnifeOptionNapi>(env, args[1]);
    // 设置context
    imageKnifeOption->ParseContext(env, args[contextIndex]);

    // 获取AnimatorOption
    auto animatorOption = std::make_shared<AnimatorOptionNapi>(env, args[animatorOptionIndex]);

    auto imageNode =  ImageKnifeInternal::GetInstance().GetImageNode(componentId);
    if (imageNode != nullptr) {
        imageNode->Reuse();
        ImageKnife::GetInstance().CancelRequest(imageNode->GetImageKnifeRequest());
        imageNode->UpdateAnimatorOption(animatorOption);
        // 通过imageKnifeOption 更新请求
        imageNode->UpdateImageKnifeRequest(imageKnifeOption);
        ImageKnifeInternal::GetInstance().Execute(imageNode->GetImageKnifeRequest());
    }
    return nullptr;
}

napi_value ImageKnifeNapi::ControlAnimatorImage(napi_env env, napi_callback_info info)
{
    size_t argc = 3;
    const size_t animatorOptionIndex = 1;
    napi_value args[3] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取componentId
    size_t length;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &length);
    char componentId[length + 1];
    napi_get_value_string_utf8(env, args[0], componentId, length + 1, nullptr);

    // 获取AnimatorOption
    auto animatorOption = std::make_shared<AnimatorOptionNapi>(env, args[animatorOptionIndex]);

    auto imageNode =  ImageKnifeInternal::GetInstance().GetImageNode(componentId);
    if (imageNode != nullptr) {
        imageNode->UpdateAnimatorOption(animatorOption);
    }
    return nullptr;
}

napi_value ImageKnifeNapi::ClearAnimatorImage(napi_env env, napi_callback_info info)
{
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取componentId
    size_t length;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &length);
    char componentId[length + 1];
    napi_get_value_string_utf8(env, args[0], componentId, length + 1, nullptr);

    auto imageNode =  ImageKnifeInternal::GetInstance().GetImageNode(componentId);
    if (imageNode != nullptr) {
        imageNode->Clear();
        ImageKnife::GetInstance().CancelRequest(imageNode->GetImageKnifeRequest());
    }
    return nullptr;
}

napi_value ImageKnifeNapi::DestroyAnimatorImage(napi_env env, napi_callback_info info)
{
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 获取componentId
    size_t length;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &length);
    char componentId[length + 1];
    napi_get_value_string_utf8(env, args[0], componentId, length + 1, nullptr);

    auto imageNode =  ImageKnifeInternal::GetInstance().GetImageNode(componentId);
    if (imageNode != nullptr) {
        ImageKnife::GetInstance().CancelRequest(imageNode->GetImageKnifeRequest());
        ImageKnifeInternal::GetInstance().DisposeRootNode(componentId);
    }
    return nullptr;
}

napi_value ImageKnifeNapi::GetCacheLimitSize(napi_env env, napi_callback_info info)
{
    // 获取cacheStrategy参数
    napi_status status;
    size_t expectedArgCount = 1;
    napi_value jsCacheStrategy;
    status = napi_get_cb_info(env, info, &expectedArgCount, &jsCacheStrategy, nullptr, nullptr);
    int cacheStrategy = 0;
    status = napi_get_value_int32(env, jsCacheStrategy, &cacheStrategy);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN,
                     "ImageKnifeNapi::GetCacheLimitSize",
                     "Failed to get 'cacheStrategy' parameter");
    }

    int64_t cacheLimitSize = ImageKnife::GetInstance().GetCacheLimitSize(static_cast<CacheStrategy>(cacheStrategy));
    napi_value jsCacheLimitSize;
    status = napi_create_bigint_int64(env, cacheLimitSize, &jsCacheLimitSize);
    if (status != napi_ok) {
        std::string errorMessage = "Failed to convert C++ value " +
                                    std::to_string(cacheLimitSize) + " to JavaScript BigInt";
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN,
                     "ImageKnifeNapi::GetCacheLimitSize",
                     "Failed to convert C++ value %{public}ld to JavaScript BigInt", cacheLimitSize);
        napi_throw_error(env, nullptr, errorMessage.c_str());
        return nullptr;
    }

    return jsCacheLimitSize;
}

napi_value ImageKnifeNapi::GetCurrentCacheNum(napi_env env, napi_callback_info info)
{
    // 获取cacheStrategy参数
    napi_status status;
    size_t expectedArgCount = 1;
    napi_value jsCacheStrategy;
    status = napi_get_cb_info(env, info, &expectedArgCount, &jsCacheStrategy, nullptr, nullptr);
    int cacheStrategy = 0;
    status = napi_get_value_int32(env, jsCacheStrategy, &cacheStrategy);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN,
                     "ImageKnifeNapi::GetCurrentCacheNum",
                     "Failed to get 'cacheStrategy' parameter");
    }

    int64_t currentCacheNum = ImageKnife::GetInstance().GetCurrentCacheNum(static_cast<CacheStrategy>(cacheStrategy));
    napi_value jsCurrentCacheNum;
    status = napi_create_bigint_int64(env, currentCacheNum, &jsCurrentCacheNum);
    if (status != napi_ok) {
        std::string errorMessage = "Failed to convert C++ value " +
                                    std::to_string(currentCacheNum) + " to JavaScript BigInt";
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN,
                     "ImageKnifeNapi::GetCurrentCacheNum",
                     "Failed to convert C++ value %{public}ld to JavaScript BigInt", currentCacheNum);
        napi_throw_error(env, nullptr, errorMessage.c_str());
        return nullptr;
    }

    return jsCurrentCacheNum;
}

napi_value ImageKnifeNapi::GetCurrentCacheSize(napi_env env, napi_callback_info info)
{
    // 获取cacheStrategy参数
    napi_status status;
    size_t expectedArgCount = 1;
    napi_value jsCacheStrategy;
    status = napi_get_cb_info(env, info, &expectedArgCount, &jsCacheStrategy, nullptr, nullptr);
    int cacheStrategy = 0;
    status = napi_get_value_int32(env, jsCacheStrategy, &cacheStrategy);
    if (status != napi_ok) {
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN,
                     "ImageKnifeNapi::GetCurrentCacheSize",
                     "Failed to get 'cacheStrategy' parameter");
    }

    int64_t currenCacheSize = ImageKnife::GetInstance().GetCurrentCacheSize(static_cast<CacheStrategy>(cacheStrategy));
    napi_value jsCurrentCacheSize;
    status = napi_create_bigint_int64(env, currenCacheSize, &jsCurrentCacheSize);
    if (status != napi_ok) {
        std::string errorMessage = "Failed to convert C++ value " +
                                    std::to_string(currenCacheSize) + " to JavaScript BigInt";
        OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN,
                     "ImageKnifeNapi::GetCurrentCacheSize",
                     "Failed to convert C++ value %{public}ld to JavaScript BigInt", currenCacheSize);
        napi_throw_error(env, nullptr, errorMessage.c_str());
        return nullptr;
    }

    return jsCurrentCacheSize;
}

extern std::multimap<std::string, std::string> &GetGlobaHttpHeaders();

napi_value ImageKnifeNapi::AddHeader(napi_env env, napi_callback_info info)
{
    const size_t argsLength = 2;
    const size_t maxKeyLength = 128;
    const size_t maxValueLength = 256;
    napi_value argv[argsLength];
    size_t args = argsLength;
    napi_get_cb_info(env, info, &args, argv, nullptr, nullptr);

    char key[maxKeyLength] = {0};
    size_t keyLength = 0;
    napi_get_value_string_utf8(env, argv[0], key, maxKeyLength, &keyLength);
    key[keyLength] = 0;

    char value[maxValueLength] = {0};
    size_t valueLength = 0;
    napi_get_value_string_utf8(env, argv[1], value, maxValueLength, &valueLength);
    value[valueLength] = 0;

    auto &httpHeaders = GetGlobaHttpHeaders();
    httpHeaders.insert(std::make_pair(std::string(key), std::string(value)));

    return nullptr;
}

napi_value ImageKnifeNapi::DeleteHeader(napi_env env, napi_callback_info info)
{
    const size_t maxKeyLength = 128;
    napi_value jsKey;
    size_t args = 1;
    napi_get_cb_info(env, info, &args, &jsKey, nullptr, nullptr);

    char key[maxKeyLength] = {0};
    size_t keyLength = 0;
    napi_get_value_string_utf8(env, jsKey, key, maxKeyLength, &keyLength);
    key[keyLength] = 0;

    auto &httpHeaders = GetGlobaHttpHeaders();
    httpHeaders.erase(std::string(key));
    return nullptr;
}

napi_value ImageKnifeNapi::RemoveAllMemoryCache(napi_env env, napi_callback_info info)
{
    ImageKnife::GetInstance().RemoveAllMemoryCache();
    return nullptr;
}

napi_value ImageKnifeNapi::RemoveMemoryCache(napi_env env, napi_callback_info info)
{
    napi_status status;
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    napi_value jsImageKnifeOption = args[0];
    auto imageKnifeOption = std::make_shared<ImageKnifeOptionNapi>(env, jsImageKnifeOption);
    ImageKnife::GetInstance().RemoveMemoryCache(imageKnifeOption);
    return nullptr;
}

napi_value ImageKnifeNapi::RemoveAllFileCache(napi_env env, napi_callback_info info)
{
    TaskWorker *taskWorker = TaskWorker::GetInstance();
    if (taskWorker == nullptr) {
        return nullptr;
    }
    AsyncFunc asyncFunc = [](void *data) {
        ImageKnife::GetInstance().RemoveAllFileAsync();
    };
    return taskWorker->PushTask(asyncFunc, nullptr, nullptr, "RemoveAllFileCache");
}

napi_value ImageKnifeNapi::RemoveFileCache(napi_env env, napi_callback_info info)
{
    napi_value jsImageKnifeOption;
    size_t args = 1;
    napi_get_cb_info(env, info, &args, &jsImageKnifeOption, nullptr, nullptr);
    auto imageKnifeOption = std::make_shared<ImageKnifeOptionNapi>(env, jsImageKnifeOption);
    std::shared_future<bool> future = ImageKnife::GetInstance().RemoveFileAsync(imageKnifeOption);
    bool result = future.get();
    napi_value value = nullptr;
    napi_get_boolean(env, result, &value);
    return value;
}
} // end of namespace
